import { createLoading } from '/@/components/Loading';
import type { Directive, App } from 'vue';

/**
 * 在元素上添加 loading 效果的 Vue 自定义指令
 * @example
 * <div ref="spinRef" :style="spinStyle" v-loading="loading" :loading-tip="loadingTip">
 */
const loadingDirective: Directive = {
  //在指令绑定的元素被插入页面时进行初始化操作
  mounted(el, binding) {
    const tip = el.getAttribute('loading-tip');
    const background = el.getAttribute('loading-background');
    const size = el.getAttribute('loading-size');
    // 检查是否使用了 .fullscreen 修饰符
    const fullscreen = !!binding.modifiers.fullscreen;
    const instance = createLoading(
      {
        tip,
        background,
        size: size || 'large',
        loading: !!binding.value,
        absolute: !fullscreen,
      },
      fullscreen ? document.body : el,
    );
    el.instance = instance;
  },
  //在指令绑定的元素所在组件的 VNode 更新时，根据绑定值的变化更新 loading 实例状态
  updated(el, binding) {
    const instance = el.instance;
    if (!instance) return;
    instance.setTip(el.getAttribute('loading-tip'));
    if (binding.oldValue !== binding.value) {
      instance.setLoading?.(binding.value && !instance.loading);
    }
  },
  //在指令绑定的元素从页面中移除时进行清理操作，关闭 loading 实例
  unmounted(el) {
    el?.instance?.close();
  },
};

export function setupLoadingDirective(app: App) {
  app.directive('loading', loadingDirective);
}

export default loadingDirective;
